#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>

void run_shell() {
    char command[1024];
    char* args[64];

    while (1) {
        char cwd[1024];
        if (getcwd(cwd, sizeof(cwd)) != NULL) {
            printf("[%s] myshell> ", cwd);
        } else {
            perror("getcwd failed");
            printf("myshell> ");
        }

        if (fgets(command, sizeof(command), stdin) == NULL)
            continue;

        if (command[strlen(command) - 1] == '\n') {
            command[strlen(command) - 1] = '\0';
        }

        if (strcmp(command, "exit") == 0) break;

        // ✅ 多管道处理
        if (strchr(command, '|')) {
            char* cmds[10];
            int cmd_count = 0;

            char* token = strtok(command, "|");
            while (token && cmd_count < 10) {
                while (*token == ' ') token++; // 去前导空格
                cmds[cmd_count++] = token;
                token = strtok(NULL, "|");
            }

            int pipefd[2], prev_fd = -1;

            for (int i = 0; i < cmd_count; i++) {
                if (i < cmd_count - 1 && pipe(pipefd) < 0) {
                    perror("pipe failed");
                    exit(1);
                }

                pid_t pid = fork();
                if (pid == 0) {
                    if (prev_fd != -1) {
                        dup2(prev_fd, STDIN_FILENO);
                        close(prev_fd);
                    }
                    if (i < cmd_count - 1) {
                        close(pipefd[0]);
                        dup2(pipefd[1], STDOUT_FILENO);
                        close(pipefd[1]);
                    }

                    // 解析当前命令参数
                    char* local_args[64];
                    int j = 0;
                    char* arg = strtok(cmds[i], " ");
                    while (arg) {
                        local_args[j++] = arg;
                        arg = strtok(NULL, " ");
                    }
                    local_args[j] = NULL;

                    execvp(local_args[0], local_args);
                    perror("exec failed");
                    exit(1);
                }

                // 父进程清理
                if (prev_fd != -1) close(prev_fd);
                if (i < cmd_count - 1) {
                    close(pipefd[1]);
                    prev_fd = pipefd[0];
                }
            }

            for (int i = 0; i < cmd_count; i++) wait(NULL);
            continue;
        }

        // ✅ 重定向处理
        char output_file[128] = {0};
        char input_file[128] = {0};
        int append_mode = 0;

        char* input_redirect = strchr(command, '<');
        char* output_redirect = strstr(command, ">>");
        if (output_redirect) {
            append_mode = 1;
        } else {
            output_redirect = strchr(command, '>');
        }

        if (input_redirect) {
            *input_redirect = '\0';
            input_redirect++;
            while (*input_redirect == ' ') input_redirect++;
            sscanf(input_redirect, "%127s", input_file);
        }

        if (output_redirect) {
            *output_redirect = '\0';
            output_redirect += append_mode ? 2 : 1;
            while (*output_redirect == ' ') output_redirect++;
            sscanf(output_redirect, "%127s", output_file);
        }

        // 分割命令为参数
        int i = 0;
        char* token = strtok(command, " ");
        while (token != NULL) {
            args[i++] = token;
            token = strtok(NULL, " ");
        }
        args[i] = NULL;

        // cd 命令单独处理
        if (args[0] && strcmp(args[0], "cd") == 0) {
            if (args[1] == NULL) {
                fprintf(stderr, "cd: missing operand\n");
            } else if (chdir(args[1]) != 0) {
                perror("cd failed");
            }
            continue;
        }

        // 普通命令执行
        pid_t pid = fork();
        if (pid == 0) {
            if (output_file[0] != '\0') {
                int flags = O_WRONLY | O_CREAT | (append_mode ? O_APPEND : O_TRUNC);
                int fd = open(output_file, flags, 0644);
                if (fd < 0) {
                    perror("open failed");
                    exit(1);
                }
                dup2(fd, STDOUT_FILENO);
                close(fd);
            }
            if (input_file[0] != '\0') {
                int fd = open(input_file, O_RDONLY);
                if (fd < 0) {
                    perror("open input failed");
                    exit(1);
                }
                dup2(fd, STDIN_FILENO);
                close(fd);
            }

            execvp(args[0], args);
            perror("exec failed");
            exit(1);
        } else if (pid > 0) {
            wait(NULL);
        } else {
            perror("fork failed");
        }
    }
}

